package per.poker.chedapao;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ConcurrentHashSet;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.FlowPane;
import javafx.scene.paint.Color;
import javafx.stage.StageStyle;
import javafx.util.Pair;
import lombok.extern.slf4j.Slf4j;
import per.poker.common.CommonService;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;
import java.util.stream.Collectors;

@Slf4j
public class ChedapaoService extends ChedapaoData {

    private Game game;
    private Thread thread = null;
    private final int waitTime = 10;

    public void startGame() throws InterruptedException {

        thread = Thread.currentThread();
        discard.setDisable(true);
        pass.setDisable(true);
        flip.setDisable(true);

        int start = RandomUtil.randomInt(0, 4);
        Player startPlayer = game.getPlayerList().get(start);
        startPlayer.setCanDiscard(true);
        AtomicInteger idx = new AtomicInteger(start);

        //DEBUG
        /*Player startPlayer = game.getPlayerList().get(1);
        startPlayer.setCanDiscard(true);
        AtomicInteger idx = new AtomicInteger(1);*/

        //出牌后先确认是否翻牌，都不翻后才可以继续出牌
        while (game.getIsStarted()) {
            startPlayer = game.getPlayerList().get(idx.get() % 4);
            if (startPlayer.getFinished()) {
                idx.incrementAndGet();
                continue;
            }
            if (end(startPlayer)) {
                break;
            }
            Thread.sleep(waitTime);

            //如果出完牌但是全部都跳过了，既不翻牌也不跟牌，那么出牌的玩家继续
            boolean allPassedFollow = game.getPlayerList().stream()
                    .filter(p -> !p.getFinished())
                    .filter(p -> ObjectUtil.notEqual(p, game.getLastPlayer()))
                    .allMatch(Player::getHasPassedFollow);
            boolean allPassedFlip = game.getPlayerList().stream()
                    .filter(p -> !p.getFinished())
                    .filter(p -> ObjectUtil.notEqual(p, game.getLastPlayer()))
                    .allMatch(Player::getHasPassedFlip);

            //log.info("——————" + game.toString() + "——————");
            if (allPassedFollow) {
                showTip(StrUtil.format("无人跟牌，玩家 {} 继续出牌", game.getLastPlayer().getName()));
                //保存每个玩家各自过掉的牌
                saveCard();

                game.getFieldList().clear();
                game.setPresentCardNum(null);
                game.setLastPlayer(null);

                for (Player player : game.getPlayerList()) {
                    player.setCanDiscard(false);
                    player.setCanFlip(false);
                    player.setCanFollow(false);
                    player.setHasPassedFlip(false);
                    player.setHasPassedFollow(false);
                }
                startPlayer.setCanDiscard(true);

                game.getPlayerList().stream().filter(p -> p.getCards().isEmpty()).forEach(p -> p.setFinished(true));


                if (startPlayer.getCards().isEmpty()) {
                    showTip(StrUtil.format("玩家 {} 成功逃脱", startPlayer.getName()));

                    //找到下家
                    Player p;
                    do {
                        List<Player> playerList = game.getPlayerList();
                        int index = (idx.get() + 1) % 4;
                        p = playerList.get(index);
                        idx.incrementAndGet();
                    } while (p.getFinished());
                    for (Player player : game.getPlayerList()) {
                        player.setCanDiscard(false);
                        player.setCanFlip(false);
                        player.setCanFollow(false);
                        player.setHasPassedFlip(false);
                        player.setHasPassedFollow(false);
                    }
                    p.setCanDiscard(true);
                    continue;
                }
            }

            if (allPassedFlip && CharSequenceUtil.isNotBlank(game.getPresentCardNum()) && ObjectUtil.equal(startPlayer, game.getLastPlayer())) {
                log.info("无人翻牌，下家可以跟牌");
                //找到下家
                Player p;
                do {
                    List<Player> playerList = game.getPlayerList();
                    int index = (idx.get() + 1) % 4;
                    p = playerList.get(index);
                    idx.incrementAndGet();
                } while (p.getFinished());
                log.info("当前玩家 {} 的下家是 {}", startPlayer.getName(), p.getName());
                showTip(StrUtil.format("————无人翻牌，{} 可以跟牌————", p.getName()));
                p.setCanFollow(true);
                p.setCanFlip(false);
                p.setCanDiscard(false);
                p.setHasPassedFollow(false);
                p.setHasPassedFlip(true);
                continue;
            }

            showTip(StrUtil.format("————————轮到玩家 {}————————", startPlayer.getName()));
            log.info(startPlayer.toString());
            //print();
            //轮到玩家
            if ("south".equals(startPlayer.getName())) {

                //没牌的话说明轮到自己出牌
                if (game.getFieldList().isEmpty()) {

                    log.info("south准备出牌");
                    startPlayer.setCanDiscard(true);
                    startPlayer.setCanFlip(false);
                    startPlayer.setCanFollow(false);
                    flip.setDisable(true);
                    pass.setDisable(true);
                    discard.setDisable(false);
                    cardPane.setDisable(false);

                    LockSupport.park();

                    //轮到下家
                    Player p;
                    do {
                        List<Player> playerList = game.getPlayerList();
                        int index = (idx.get() + 1) % 4;
                        p = playerList.get(index);
                        idx.incrementAndGet();
                    } while (p.getFinished());
                    log.info("当前玩家 {} 的下家是 {}", startPlayer.getName(), p.getName());
                    p.setCanFlip(true);
                    p.setCanDiscard(false);
                    p.setCanFollow(false);
                    p.setHasPassedFollow(false);
                    p.setHasPassedFlip(false);
                    continue;
                }
                //可以跟牌，也可以跳过
                else if (startPlayer.getCanFollow()) {

                    log.info("south准备跟牌或跳过");
                    startPlayer.setCanDiscard(false);
                    startPlayer.setCanFlip(false);

                    flip.setDisable(true);
                    pass.setDisable(false);
                    discard.setDisable(false);
                    cardPane.setDisable(true);

                    LockSupport.park();

                    //轮到下家
                    Player p;
                    do {
                        List<Player> playerList = game.getPlayerList();
                        int index = (idx.get() + 1) % 4;
                        p = playerList.get(index);
                        idx.incrementAndGet();
                    } while (p.getFinished());
                    log.info("当前玩家 {} 的下家是 {}", startPlayer.getName(), p.getName());
                    if (startPlayer.getHasPassedFollow()){
                        p.setCanFlip(false);
                        p.setCanDiscard(false);
                        p.setCanFollow(true);
                        p.setHasPassedFollow(false);
                        p.setHasPassedFlip(true);
                    }else {
                        p.setCanFlip(true);
                        p.setCanDiscard(false);
                        p.setCanFollow(false);
                        p.setHasPassedFollow(false);
                        p.setHasPassedFlip(false);
                    }
                    continue;

                }
                //可以翻牌，也可以跳过
                else if (startPlayer.getCanFlip()) {

                    log.info("south准备翻牌或跳过");
                    startPlayer.setCanDiscard(false);
                    startPlayer.setCanFollow(false);

                    flip.setDisable(false);
                    pass.setDisable(false);
                    discard.setDisable(true);
                    cardPane.setDisable(true);

                    LockSupport.park();

                    //跳过就找到下家
                    if (startPlayer.getHasPassedFlip()) {
                        Player p;
                        do {
                            List<Player> playerList = game.getPlayerList();
                            int index = (idx.get() + 1) % 4;
                            p = playerList.get(index);
                            idx.incrementAndGet();
                        } while (p.getFinished());
                        log.info("当前玩家 {} 的下家是 {}", startPlayer.getName(), p.getName());
                        p.setCanFlip(true);
                        p.setCanDiscard(false);
                        p.setCanFollow(false);
                        p.setHasPassedFollow(false);
                        p.setHasPassedFlip(false);
                        continue;
                    }
                    //判断翻牌结果
                    //自己继续出牌，如果自己已经出完就下家出
                    if (ObjectUtil.equal(startPlayer.getName(), game.getLastPlayer().getName())) {

                        if (startPlayer.getFinished()) {
                            Player p;
                            do {
                                List<Player> playerList = game.getPlayerList();
                                int index = (idx.get() + 1) % 4;
                                p = playerList.get(index);
                                idx.incrementAndGet();
                            } while (p.getFinished());
                            log.info("由当前玩家 {} 下家 {} 继续出牌", startPlayer.getName(), p.getName());
                            p.setCanFlip(false);
                            p.setCanDiscard(true);
                            p.setCanFollow(false);
                            p.setHasPassedFollow(false);
                            p.setHasPassedFlip(false);
                            game.setLastPlayer(p);

                        } else {
                            log.info("由当前玩家 {} 继续出牌", startPlayer.getName());
                            startPlayer.setCanFlip(false);
                            startPlayer.setCanDiscard(true);
                            startPlayer.setCanFollow(false);
                            startPlayer.setHasPassedFollow(false);
                            startPlayer.setHasPassedFlip(false);
                            game.setLastPlayer(startPlayer);
                        }
                        continue;
                    }
                    //出牌玩家出牌，但是有可能已经出完，就找其下家
                    else {

                        if (game.getLastPlayer().getFinished()) {

                            Player p;
                            int index = game.getPlayerList().indexOf(game.getLastPlayer());
                            idx.set(index);
                            do {
                                idx.incrementAndGet();
                                p = game.getPlayerList().get(idx.get());
                            } while (p.getFinished());
                            log.info("由出牌玩家 {} 下家 {} 继续出牌", game.getLastPlayer().getName(), p.getName());
                            p.setCanFlip(false);
                            p.setCanDiscard(true);
                            p.setCanFollow(false);
                            p.setHasPassedFollow(false);
                            p.setHasPassedFlip(false);
                            game.setLastPlayer(p);

                        } else {
                            log.info("由出牌玩家 {} 继续出牌", game.getLastPlayer().getName());
                            game.getLastPlayer().setCanFlip(false);
                            game.getLastPlayer().setCanDiscard(true);
                            game.getLastPlayer().setCanFollow(false);
                            game.getLastPlayer().setHasPassedFollow(false);
                            game.getLastPlayer().setHasPassedFlip(false);
                            int index = game.getPlayerList().indexOf(game.getLastPlayer());
                            idx.set(index);
                        }

                        continue;
                    }

                }

            }
            //轮到电脑
            else {

                discard.setDisable(true);
                pass.setDisable(true);
                flip.setDisable(true);

                //0-继续  1-轮到下家翻牌或跳过 2-出牌玩家继续出牌 3-当前玩家继续出牌 4-当前玩家下家跟牌 5-出牌玩家的下家出牌
                int exit = 0;
                //失败太多次就跳过
                int flipCounter = 0;
                do {
                    int ranAction = RandomUtil.randomInt(1, 6);
                    ActionEnum action = EnumUtil.getBy(ActionEnum.class, a -> ObjectUtil.equal(a.getNum(), ranAction));

                    //可以出牌
                    if (CollUtil.isNotEmpty(startPlayer.getCards()) && action == ActionEnum.DISCARD && startPlayer.getCanDiscard()) {
                        log.info("玩家 {} 出牌", startPlayer.getName());
                        discard(startPlayer);
                        exit = 1;
                    }
                    //可以跟牌
                    else if (CollUtil.isNotEmpty(startPlayer.getCards()) && action == ActionEnum.FOLLOW && startPlayer.getCanFollow()) {
                        log.info("玩家 {} 也许跟牌", startPlayer.getName());
                        //自己出过真牌之后，不再倾向于跟牌
                        //如果过了假牌再轮到自己，倾向于出真牌
                        boolean passTrueCardFlag = false;
                        boolean useTrueFlag = true;
                        for (Map<String, List<String>> map : game.getFieldList()) {
                            if (map.get(startPlayer.getName()) != null) {
                                //当前玩家出过的牌
                                List<String> ls = map.get(startPlayer.getName()).stream()
                                        .map(c -> c.substring(1)).collect(Collectors.toList());
                                if (ls.contains(game.getPresentCardNum())) {

                                    if (RandomUtil.randomInt(0, 100) < 75) {
                                        passTrueCardFlag = true;
                                    } else {
                                        useTrueFlag = false;
                                    }
                                    break;
                                }
                            }
                        }
                        if (passTrueCardFlag) {
                            continue;
                        }


                        log.info("玩家 {} 跟牌", startPlayer.getName());
                        follow(startPlayer, useTrueFlag);
                        exit = 1;
                    }
                    //可以翻牌
                    else if (CollUtil.isNotEmpty(startPlayer.getCards()) && action == ActionEnum.FLIP && startPlayer.getCanFlip()) {

                        log.info("玩家 {} 也许翻牌", startPlayer.getName());
                        //如果上家出了3张4，自己有两张4，那么必定翻牌
                        int fakeNum = CollUtil.getLast(CollUtil.getLast(game.getFieldList()).values()).size();
                        int ownNum = (int) startPlayer.getCards().stream()
                                .filter(c -> ObjectUtil.equals(c.substring(1), game.getPresentCardNum())).count();

                        if (ownNum > fakeNum) {
                            log.info("必定翻牌");
                        } else {
                            //几率不翻
                            if (RandomUtil.randomInt(0, 100) < 95) {
                                log.info("{} 不打算翻牌...", startPlayer.getName());
                                flipCounter++;
                                continue;
                            }
                        }

                        log.info("玩家 {} 翻牌", startPlayer.getName());
                        boolean flipResult = flip(startPlayer);
                        //当前玩家收走所有的牌，由上次出牌玩家继续出牌
                        if (flipResult) {

                            if (game.getLastPlayer().getCards().isEmpty()) {
                                showTip(StrUtil.format("出牌玩家 {} 已经逃脱，轮到其下家", game.getLastPlayer().getName()));
                                game.getLastPlayer().setFinished(true);
                                exit = 5;
                            } else {

                                showTip(StrUtil.format("由出牌玩家 {} 继续出牌", game.getLastPlayer().getName()));
                                game.getLastPlayer().setCanDiscard(true);
                                game.getLastPlayer().setCanFlip(false);
                                game.getLastPlayer().setCanFollow(false);
                                startPlayer.setHasPassedFollow(false);
                                startPlayer.setHasPassedFlip(false);

                                game.getPlayerList().stream()
                                        .filter(c -> ObjectUtil.notEqual(c.getName(), game.getLastPlayer().getName()))
                                        .forEach(c -> {
                                            c.setHasPassedFlip(false);
                                            c.setHasPassedFollow(false);
                                            c.setCanDiscard(false);
                                            c.setCanFollow(false);
                                            c.setCanFlip(true);
                                        });

                                exit = 2;
                            }

                        } else {

                            showTip(StrUtil.format("由当前玩家 {} 出牌", startPlayer.getName()));
                            startPlayer.setCanDiscard(true);
                            startPlayer.setCanFlip(false);
                            startPlayer.setCanFollow(false);
                            startPlayer.setHasPassedFollow(false);
                            startPlayer.setHasPassedFlip(false);

                            Player finalStartPlayer1 = startPlayer;
                            game.getPlayerList().stream()
                                    .filter(c -> ObjectUtil.notEqual(c.getName(), finalStartPlayer1.getName()))
                                    .forEach(c -> {
                                        c.setHasPassedFlip(false);
                                        c.setHasPassedFollow(false);
                                        c.setCanDiscard(false);
                                        c.setCanFollow(false);
                                        c.setCanFlip(true);
                                    });

                            exit = 3;
                        }
                    }
                    //跳过翻牌   场上有牌才能跳过，否则必须出牌
                    else if (CollUtil.isNotEmpty(game.getFieldList()) && (flipCounter >= 3 || action == ActionEnum.PASS_FLIP) && !startPlayer.getHasPassedFlip()) {
                        //知道对方有那张牌的时候，不倾向于翻牌
                        log.info("玩家 {} 也许跳过翻牌", startPlayer.getName());
                        String lastName = CollUtil.getLast(CollUtil.getLast(game.getFieldList()).keySet());
                        if (startPlayer.getExposedCards().get(lastName).contains(game.getPresentCardNum())) {
                            if (RandomUtil.randomInt(0, 100) > 90){
                                continue;
                            }
                        }
                        showTip(StrUtil.format("玩家 {} 跳过翻牌", startPlayer.getName()));
                        passFlip(startPlayer);
                        exit = 1;
                    }
                    //跳过跟牌
                    else if (CollUtil.isNotEmpty(game.getFieldList()) && action == ActionEnum.PASS_FOLLOW &&
                            startPlayer.getHasPassedFlip() && !startPlayer.getHasPassedFollow()) {

                        log.info("玩家 {} 也许跳过跟牌", startPlayer.getName());
                        //自己出过假牌之后，倾向于跟假牌
                        boolean notPassFollow = false;
                        for (Map<String, List<String>> map : game.getFieldList()) {
                            if (map.get(startPlayer.getName()) != null) {
                                //当前玩家出过的牌
                                List<String> ls = map.get(startPlayer.getName()).stream()
                                        .map(c -> c.substring(1)).collect(Collectors.toList());
                                if (!ls.contains(game.getPresentCardNum()) && RandomUtil.randomInt(0, 100) < 75) {
                                    notPassFollow = true;
                                    break;
                                }
                            }
                        }
                        if (notPassFollow) {
                            continue;
                        }
                        //场上牌数超过6张，倾向于跳过
                        int allCardLen = 0;
                        for (Map<String, List<String>> map : game.getFieldList()) {
                            allCardLen += map.values().size();
                        }
                        if (allCardLen > 6) {
                            if (RandomUtil.randomInt(0, 100) >= 75) {
                                continue;
                            }
                        }
                        showTip(StrUtil.format("玩家 {} 跳过跟牌", startPlayer.getName()));
                        passFollow(startPlayer);
                        exit = 4;
                    }

                } while (exit == 0);
                //1-轮到下家翻牌或跳过
                if (exit == 1) {
                    //找到下家
                    Player p;
                    do {
                        List<Player> playerList = game.getPlayerList();
                        int index = (idx.get() + 1) % 4;
                        p = playerList.get(index);
                        idx.incrementAndGet();
                    } while (p.getFinished());
                    log.info("当前玩家 {} 的下家是 {}", startPlayer.getName(), p.getName());
                    p.setCanFlip(true);
                    p.setCanDiscard(false);
                    p.setCanFollow(false);
                    p.setHasPassedFollow(false);
                    p.setHasPassedFlip(false);
                    continue;

                }
                //2-出牌玩家继续出牌
                else if (exit == 2) {
                    int i = game.getPlayerList().indexOf(game.getLastPlayer());
                    idx.set(i);
                    continue;
                }
                //3-当前玩家继续出牌
                else if (exit == 3) {
                    continue;
                }
                //当前玩家下家跟牌
                else if (exit == 4) {
                    //找到下家
                    Player p;
                    do {
                        List<Player> playerList = game.getPlayerList();
                        int index = (idx.get() + 1) % 4;
                        p = playerList.get(index);
                        idx.incrementAndGet();
                    } while (p.getFinished());
                    log.info("当前玩家 {} 的下家是 {}", startPlayer.getName(), p.getName());
                    p.setCanFlip(false);
                    p.setCanDiscard(false);
                    p.setCanFollow(true);
                    p.setHasPassedFollow(false);
                    p.setHasPassedFlip(true);
                    continue;
                }
                //出牌玩家的下家出牌
                else {
                    //找到上次出牌的玩家
                    int i = game.getPlayerList().indexOf(game.getLastPlayer());
                    idx.set(i);
                    //找到其下家
                    Player p;
                    do {
                        List<Player> playerList = game.getPlayerList();
                        int index = (idx.get() + 1) % 4;
                        p = playerList.get(index);
                        idx.incrementAndGet();
                    } while (p.getFinished());
                    p.setCanFlip(false);
                    p.setCanDiscard(true);
                    p.setCanFollow(false);
                    p.setHasPassedFollow(false);
                    p.setHasPassedFlip(false);
                    continue;
                }

            }

            //轮到下家
            //idx.incrementAndGet();
            Player p;
            do {
                List<Player> playerList = game.getPlayerList();
                int index = (idx.get() + 1) % 4;
                p = playerList.get(index);
                idx.incrementAndGet();
            } while (p.getFinished());
            log.info("当前玩家 {} 的下家是 {}", startPlayer.getName(), p.getName());
            p.setCanFlip(true);
            p.setCanDiscard(false);
            p.setCanFollow(false);
            p.setHasPassedFollow(false);
            p.setHasPassedFlip(false);

        }

    }

    private void passFollow(Player startPlayer) {
        //一般超过6张牌则倾向于不跟牌
        startPlayer.setHasPassedFollow(true);
    }

    private void passFlip(Player startPlayer) {
        //知道对方有那张牌的时候，不倾向于翻牌
        startPlayer.setHasPassedFlip(true);
    }

    private boolean flip(Player startPlayer) throws InterruptedException {
        List<String> ls = new LinkedList<>(CollUtil.getLast(CollUtil.getLast(game.getFieldList()).values()));
        log.info("{} 翻牌结果: {}", startPlayer.getName(), ls);

        Label l = new Label();
        l.setPrefWidth(670);
        l.setPrefHeight(36);
        l.setText(StrUtil.format("————————玩家 {} 翻牌————————", startPlayer.getName()));
        l.setAlignment(Pos.CENTER);

        FlowPane flowPane = new FlowPane();
        flowPane.setPrefWidth(670);
        flowPane.setPrefHeight(114);

        for (String card : ls) {

            ImageView imageView = new ImageView();
            imageView.setId(card);
            imageView.setFitWidth(53);
            imageView.setFitHeight(75);
            imageView.setPreserveRatio(true);
            imageView.setPickOnBounds(true);

            imageView.setImage(new Image(CommonService.getPicUrl("/img/" + card + ".jpg")));
            flowPane.getChildren().add(imageView);
        }

        Runnable runnable = () -> {
            stage.getChildren().add(l);
            stage.getChildren().add(flowPane);
            scrollPane.vvalueProperty().setValue(1.0);
        };
        CommonService.runLater(runnable);

        boolean isTrue = ls.stream().allMatch(s -> ObjectUtil.equal(s.substring(1), game.getPresentCardNum()));
        //翻的牌对得上，自己要把所有的牌收走
        if (isTrue) {

            for (Player player : game.getPlayerList()) {
                for (String s : ls) {
                    player.getExposedCards().get(startPlayer.getName()).add(s.substring(1));
                }
            }

            for (Map<String, List<String>> map : game.getFieldList()) {
                startPlayer.getCards().addAll(CollUtil.getLast(map.values()));
            }

            Collections.shuffle(startPlayer.getCards());
            log.info("玩家 {} 收回所有牌", startPlayer.getName());
            Runnable back = () -> {
                startPlayer.getPane().getChildren().clear();
                for (String s : startPlayer.getCards()) {
                    setCardFlow(startPlayer.getName(), s);
                }
            };
            CommonService.runLater(back);

            game.getPlayerList().stream().filter(p -> p.getCards().isEmpty()).forEach(p -> p.setFinished(true));

            end(startPlayer);

        }
        //对不上，上一个玩家收走
        else {

            for (Player player : game.getPlayerList()) {
                for (String s : ls) {
                    player.getExposedCards().get(game.getLastPlayer().getName()).add(s.substring(1));
                }
            }

            for (Map<String, List<String>> map : game.getFieldList()) {
                game.getLastPlayer().getCards().addAll(CollUtil.getLast(map.values()));
            }
            game.getLastPlayer().getCards().sort(Comparator.comparingInt(o ->
                    CardEnum.valueOf("_" + o.substring(1)).getNum()));

            Runnable back = () -> {
                game.getLastPlayer().getPane().getChildren().clear();
                log.info("玩家 {} 收回所有牌", game.getLastPlayer().getName());
                for (String s : game.getLastPlayer().getCards()) {
                    setCardFlow(game.getLastPlayer().getName(), s);
                }
            };
            CommonService.runLater(back);

            game.getPlayerList().stream().filter(p -> p.getCards().isEmpty()).forEach(p -> p.setFinished(true));

            end(game.getLastPlayer());

        }

        game.setPresentCardNum(null);
        game.getFieldList().clear();
        return isTrue;
    }

    private void follow(Player startPlayer, boolean useTrueFlag) throws InterruptedException {

        Map<String, Integer> countMap = new HashMap<>(16);
        for (String card : startPlayer.getCards()) {
            countMap.put(card.substring(1),
                    countMap.getOrDefault(card.substring(1), 0) + 1);
        }

        //当前点数有多少张，也是决定要出的牌数
        Integer discardNum = countMap.get(game.getPresentCardNum());
        List<Node> selectedNodes = new LinkedList<>();
        //出真牌
        if (useTrueFlag && discardNum != null) {
            selectedNodes.addAll(startPlayer.getPane().getChildren().stream()
                    .filter(c -> ObjectUtil.equals(c.getId().substring(1), game.getPresentCardNum()))
                    .collect(Collectors.toList()));
        }
        //出假牌
        else {

            if (discardNum == null) {
                discardNum = RandomUtil.randomInt(1, Math.min(3, startPlayer.getCards().size() + 1));
            }
            //要出牌的索引
            Set<Integer> ranSet = new ConcurrentHashSet<>();
            game.setPresentCardNum(game.getPresentCardNum());

            do {
                ranSet.add(RandomUtil.randomInt(0, startPlayer.getCards().size()));
            } while (ranSet.size() != discardNum);

            for (Integer ix : ranSet) {
                selectedNodes.add(startPlayer.getPane().getChildren().get(ix));
            }

        }

        Label l = new Label();
        l.setPrefWidth(670);
        l.setPrefHeight(36);
        l.setText(StrUtil.format("————————玩家 {} 跟牌: {}————————", startPlayer.getName(), discardNum + "张" + game.getPresentCardNum()));
        l.setAlignment(Pos.CENTER);

        FlowPane flowPane = new FlowPane();
        flowPane.setPrefWidth(670);
        flowPane.setPrefHeight(114);

        List<String> discardedCards = new LinkedList<>();

        for (Node node : selectedNodes) {

            discardedCards.add(node.getId());
            ImageView imageView = new ImageView();
            imageView.setId(node.getId());
            imageView.setFitWidth(53);
            imageView.setFitHeight(75);
            imageView.setPreserveRatio(true);
            imageView.setPickOnBounds(true);

            imageView.setImage(new Image(CommonService.getPicUrl("/img/vertical.jpg")));
            flowPane.getChildren().add(imageView);

            startPlayer.getCards().remove(node.getId());
        }

        Map<String, List<String>> map = new HashMap<>();
        map.put(startPlayer.getName(), discardedCards);
        game.getFieldList().add(map);
        if (game.getLastPlayer().getCards().isEmpty()) {
            log.info("玩家 {} 成功逃脱", game.getLastPlayer().getName());
            game.getLastPlayer().setFinished(true);
        }

        Runnable runnable = () -> {
            stage.getChildren().add(l);
            stage.getChildren().add(flowPane);
            startPlayer.getPane().getChildren().removeAll(selectedNodes);
            scrollPane.vvalueProperty().setValue(1.0);
        };
        CommonService.runLater(runnable);

        game.setLastPlayer(startPlayer);


    }

    private void discard(Player startPlayer) throws InterruptedException {
        //电脑出牌，随机生成true为真牌，false为假牌
        //出假牌，随机出牌
        //自己出过的牌成功过掉，那么有机会伪装成出过的牌,但是一旦被发现就不应该再出了
        Map<String, Integer> countMap = new HashMap<>(16);
        for (String card : startPlayer.getCards()) {
            countMap.put(card.substring(1),
                    countMap.getOrDefault(card.substring(1), 0) + 1);
        }
        //得到每种点数的牌数
        List<String> ls = new ArrayList<>(countMap.keySet());
        //得到要出的牌的点数
        String fakeType = ls.get(RandomUtil.randomInt(0, ls.size()));
        //当前点数有多少张，也是决定要出的牌数
        int discardNum = countMap.get(fakeType);

        List<Node> selectedNodes = new LinkedList<>();
        boolean isTruth = RandomUtil.randomBoolean();

        //剩余都是相同d牌
        if (startPlayer.getCards().stream().allMatch(c ->
                ObjectUtil.equals(c.substring(1), startPlayer.getCards().get(0).substring(1)))) {
            isTruth = true;
        }
        //出真牌
        if (isTruth) {
            String finalFakeType = fakeType;
            selectedNodes.addAll(startPlayer.getPane().getChildren().stream()
                    .filter(c -> ObjectUtil.equals(c.getId().substring(1), finalFakeType))
                    .collect(Collectors.toList()));
        }
        //出假牌
        else {
            //出过的牌没人翻过，可以再次伪装 75%概率
            for (Map.Entry<String, Boolean> entry : startPlayer.getPassCards().entrySet()) {
                if (!entry.getValue() && RandomUtil.randomInt(0, 100) < 75) {
                    fakeType = entry.getKey();
                    if (startPlayer.getCards().size() > 4) {
                        discardNum = 2;
                    } else {
                        discardNum = 1;
                    }
                    break;
                }
            }

            //要出牌的索引
            Set<Integer> ranSet = new ConcurrentHashSet<>();
            do {
                ranSet.add(RandomUtil.randomInt(0, startPlayer.getCards().size()));
            } while (ranSet.size() != discardNum);
            for (Integer ix : ranSet) {
                selectedNodes.add(startPlayer.getPane().getChildren().get(ix));
            }

        }

        game.setPresentCardNum(fakeType);

        log.info("————————玩家 {} 出牌: {}————————", startPlayer.getName(), discardNum + "张" + fakeType);
        Label l = new Label();
        l.setPrefWidth(670);
        l.setPrefHeight(36);
        l.setText(StrUtil.format("————————玩家 {} 出牌: {}————————", startPlayer.getName(), discardNum + "张" + fakeType));
        l.setAlignment(Pos.CENTER);

        FlowPane flowPane = new FlowPane();
        flowPane.setPrefWidth(670);
        flowPane.setPrefHeight(114);

        List<String> discardedCards = new LinkedList<>();

        for (Node node : selectedNodes) {

            discardedCards.add(node.getId());
            ImageView imageView = new ImageView();
            imageView.setId(node.getId());
            imageView.setFitWidth(53);
            imageView.setFitHeight(75);
            imageView.setPreserveRatio(true);
            imageView.setPickOnBounds(true);

            imageView.setImage(new Image(CommonService.getPicUrl("/img/vertical.jpg")));
            flowPane.getChildren().add(imageView);
            startPlayer.getCards().remove(node.getId());
        }

        Map<String, List<String>> map = new HashMap<>();
        map.put(startPlayer.getName(), discardedCards);
        game.getFieldList().add(map);

        Runnable runnable = () -> {
            stage.getChildren().add(l);
            stage.getChildren().add(flowPane);
            startPlayer.getPane().getChildren().removeAll(selectedNodes);
            scrollPane.vvalueProperty().setValue(1.0);
        };
        CommonService.runLater(runnable);

        game.getPlayerList().stream()
                .filter(p -> ObjectUtil.notEqual(startPlayer.getName(), p.getName()))
                .forEach(p -> {
                    p.setCanFlip(true);
                    p.setHasPassedFlip(false);
                    p.setHasPassedFollow(false);
                });
        game.setLastPlayer(startPlayer);
    }

    public void initButton() {

        ToggleGroup group = new ToggleGroup();
        cardA.setToggleGroup(group);
        card2.setToggleGroup(group);
        card3.setToggleGroup(group);
        card4.setToggleGroup(group);
        card5.setToggleGroup(group);
        card6.setToggleGroup(group);
        card7.setToggleGroup(group);
        card8.setToggleGroup(group);
        card9.setToggleGroup(group);
        card10.setToggleGroup(group);
        cardJ.setToggleGroup(group);
        cardQ.setToggleGroup(group);
        cardK.setToggleGroup(group);

        Player own = game.getPlayerList().get(1);
        discard.setOnMouseClicked(e -> {

            ToggleButton toggle = (ToggleButton) group.getSelectedToggle();
            String fakeCard;

            List<Node> selectedNodes = south.getChildren().stream()
                    .filter(c -> c.getEffect() != null)
                    .collect(Collectors.toList());
            if (selectedNodes.isEmpty()) {
                CommonService.errorDialog("未选择要出的牌");
                return;
            }
            //出牌
            if (own.getCanDiscard()) {

                if (toggle == null) {
                    CommonService.errorDialog("未选择谎报的牌");
                    return;
                } else {
                    fakeCard = toggle.getText();
                    //出了牌,先让其他玩家确定是否要翻
                    game.getPlayerList().stream()
                            .filter(p -> ObjectUtil.notEqual("south", p.getName()))
                            .forEach(p -> {
                                p.setCanFlip(true);
                                p.setHasPassedFlip(false);
                                p.setHasPassedFollow(false);
                            });
                    log.info("玩家 south 出牌");
                }

            }
            //跟牌
            else {
                fakeCard = game.getPresentCardNum();
                game.getPlayerList().stream()
                        .filter(p -> ObjectUtil.notEqual("south", p.getName()))
                        .forEach(p -> {
                            p.setCanFlip(true);
                            p.setHasPassedFlip(false);
                            p.setHasPassedFollow(false);
                        });
                log.info("玩家 south 跟牌");
            }

            int num = selectedNodes.size();

            log.info("————————玩家 south 出牌: {}————————", num + "张" + fakeCard);
            Label label = new Label();
            label.setPrefWidth(670);
            label.setPrefHeight(36);
            label.setText(StrUtil.format("————————玩家 south 出牌: {}————————", num + "张" + fakeCard));
            label.setAlignment(Pos.CENTER);

            FlowPane flowPane = new FlowPane();
            flowPane.setPrefWidth(670);
            flowPane.setPrefHeight(114);

            for (Node node : selectedNodes) {
                ImageView imageView = new ImageView();
                imageView.setId(node.getId());
                imageView.setFitWidth(53);
                imageView.setFitHeight(75);
                imageView.setPreserveRatio(true);
                imageView.setPickOnBounds(true);

                imageView.setImage(new Image(CommonService.getPicUrl("/img/vertical.jpg")));
                flowPane.getChildren().add(imageView);
            }

            stage.getChildren().add(label);
            stage.getChildren().add(flowPane);
            south.getChildren().removeAll(selectedNodes);
            scrollPane.vvalueProperty().setValue(1.0);

            List<String> nodes = selectedNodes.stream().map(Node::getId).collect(Collectors.toList());
            Map<String, List<String>> map = new HashMap<>(2);
            map.put("south", nodes);

            game.getPlayerList().get(1).getCards().removeAll(nodes);
            game.getFieldList().add(map);
            game.setLastPlayer(game.getPlayerList().get(1));
            game.setPresentCardNum(fakeCard);

            if (toggle != null) {
                toggle.setSelected(false);
            }

            LockSupport.unpark(thread);

        });

        pass.setOnMouseClicked(e -> {
            if (!game.getPlayerList().get(1).getHasPassedFlip()) {
                try {
                    showTip("玩家 south 跳过翻牌");
                } catch (InterruptedException ex) {
                    throw new RuntimeException(ex);
                }
                game.getPlayerList().get(1).setHasPassedFlip(true);
            } else {
                try {
                    showTip("玩家 south 跳过跟牌");
                } catch (InterruptedException ex) {
                    throw new RuntimeException(ex);
                }

                game.getPlayerList().get(1).setCanDiscard(false);
                game.getPlayerList().get(1).setCanFollow(false);
                game.getPlayerList().get(1).setCanFlip(false);
                game.getPlayerList().get(1).setHasPassedFollow(true);
            }
            LockSupport.unpark(thread);
        });

        flip.setOnMouseClicked(e -> {

            List<String> ls = CollUtil.getLast(CollUtil.getLast(game.getFieldList()).values());
            log.info("south 翻牌结果: {}", ls);

            Label l = new Label();
            l.setPrefWidth(670);
            l.setPrefHeight(36);
            l.setText(StrUtil.format("————————玩家 {} 翻牌————————", own.getName()));
            l.setAlignment(Pos.CENTER);

            FlowPane flowPane = new FlowPane();
            flowPane.setPrefWidth(670);
            flowPane.setPrefHeight(114);

            for (String card : ls) {

                ImageView imageView = new ImageView();
                imageView.setId(card);
                imageView.setFitWidth(53);
                imageView.setFitHeight(75);
                imageView.setPreserveRatio(true);
                imageView.setPickOnBounds(true);

                imageView.setImage(new Image(CommonService.getPicUrl("/img/" + card + ".jpg")));
                flowPane.getChildren().add(imageView);
            }

            stage.getChildren().add(l);
            stage.getChildren().add(flowPane);
            scrollPane.vvalueProperty().setValue(1.0);

            boolean isTrue = ls.stream().allMatch(s -> ObjectUtil.equal(s.substring(1), game.getPresentCardNum()));
            //翻的牌对得上，自己要把所有的牌收走
            if (isTrue) {

                for (Player player : game.getPlayerList()) {
                    for (String s : ls) {
                        player.getExposedCards().get("south").add(s.substring(1));
                    }
                }

                for (Map<String, List<String>> map : game.getFieldList()) {
                    own.getCards().addAll(CollUtil.getLast(map.values()));
                }

                own.getCards().sort(Comparator.comparingInt(o ->
                        CardEnum.valueOf("_" + o.substring(1)).getNum()));

                log.info("玩家 {} 收回所有牌", own.getName());
                own.getPane().getChildren().clear();
                for (String s : own.getCards()) {
                    setCardFlow(own.getName(), s);
                }

                game.getPlayerList().stream().filter(p -> p.getCards().isEmpty()).forEach(p -> p.setFinished(true));

                try {
                    end(own);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }

                log.info("由出牌玩家 {} 继续出牌", game.getLastPlayer().getName());
                game.getLastPlayer().setCanDiscard(true);
                game.getLastPlayer().setCanFlip(false);
                game.getLastPlayer().setCanFollow(false);

                discard.setDisable(true);
                pass.setDisable(true);
                flip.setDisable(true);
                cardPane.setDisable(true);
                own.setCanDiscard(false);
                own.setCanFlip(false);
                own.setCanFollow(false);
                own.setHasPassedFollow(false);
                own.setHasPassedFlip(false);

                //game.setLastPlayer(null);
                game.setPresentCardNum(null);
                saveCard();
                game.getFieldList().clear();

                LockSupport.unpark(thread);
            }
            //对不上，上一个玩家收走
            else {

                for (Player player : game.getPlayerList()) {
                    for (String s : ls) {
                        player.getExposedCards().get(game.getLastPlayer().getName()).add(s.substring(1));
                    }
                }

                for (Map<String, List<String>> map : game.getFieldList()) {
                    game.getLastPlayer().getCards().addAll(CollUtil.getLast(map.values()));
                }
                Collections.shuffle(game.getLastPlayer().getCards());

                game.getLastPlayer().getPane().getChildren().clear();
                log.info("玩家 {} 收回所有牌", game.getLastPlayer().getName());
                for (String s : game.getLastPlayer().getCards()) {
                    setCardFlow(game.getLastPlayer().getName(), s);
                }

                game.getPlayerList().stream().filter(p -> p.getCards().isEmpty()).forEach(p -> p.setFinished(true));

                try {
                    end(game.getLastPlayer());
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }

                log.info("由当前玩家 {} 出牌", own.getName());

                flip.setDisable(true);
                pass.setDisable(true);
                discard.setDisable(false);
                cardPane.setDisable(false);

                own.setCanDiscard(true);
                own.setCanFlip(false);
                own.setCanFollow(false);
                own.setHasPassedFlip(false);
                own.setHasPassedFollow(false);

                game.setLastPlayer(own);
                game.setPresentCardNum(null);
                saveCard();
                game.getFieldList().clear();
            }
        });
    }

    public void showCard(Map<String, List<String>> cards) {

        south.getChildren().clear();
        north.getChildren().clear();
        east.getChildren().clear();
        west.getChildren().clear();

        for (String s : cards.get("south")) {
            ImageView imageView = new ImageView();
            imageView.setId(s);
            imageView.setFitWidth(53);
            imageView.setFitHeight(75);
            imageView.setPreserveRatio(true);
            imageView.setPickOnBounds(true);

            imageView.setImage(new Image(CommonService.getPicUrl("/img/" + s + ".jpg")));
            south.getChildren().add(imageView);

            imageView.setOnMouseClicked(e -> {

                if (imageView.getEffect() == null) {
                    if (south.getChildren().stream().filter(c -> c.getEffect() != null).count() == 4) {
                        CommonService.errorDialog("出牌不能超过4张");
                        return;
                    }
                    imageView.setEffect(new DropShadow(15, Color.LIGHTSKYBLUE));
                } else {
                    imageView.setEffect(null);
                }

            });
        }

        for (String s : cards.get("north")) {
            ImageView imageView = new ImageView();
            imageView.setId(s);
            imageView.setFitWidth(53);
            imageView.setFitHeight(75);
            imageView.setPreserveRatio(true);
            imageView.setPickOnBounds(true);

            imageView.setImage(new Image(CommonService.getPicUrl("/img/vertical.jpg")));
            north.getChildren().add(imageView);
        }

        for (String s : cards.get("east")) {
            ImageView imageView = new ImageView();
            imageView.setId(s);
            imageView.setFitWidth(75);
            imageView.setFitHeight(53);
            imageView.setPreserveRatio(true);
            imageView.setPickOnBounds(true);

            imageView.setImage(new Image(CommonService.getPicUrl("/img/horizontal.jpg")));
            east.getChildren().add(imageView);
        }

        for (String s : cards.get("west")) {
            ImageView imageView = new ImageView();
            imageView.setId(s);
            imageView.setFitWidth(75);
            imageView.setFitHeight(53);
            imageView.setPreserveRatio(true);
            imageView.setPickOnBounds(true);

            imageView.setImage(new Image(CommonService.getPicUrl("/img/horizontal.jpg")));
            west.getChildren().add(imageView);
        }

        List<Player> playerList = new ArrayList<>(8);

        Map<String, Set<String>> exposedCards = new HashMap<>();
        exposedCards.put("east", new HashSet<>());
        exposedCards.put("south", new HashSet<>());
        exposedCards.put("west", new HashSet<>());
        exposedCards.put("north", new HashSet<>());

        playerList.add(new Player("east", cards.get("east"), false, false, false, false, false, false, east, new HashMap<>(), exposedCards));
        playerList.add(new Player("south", cards.get("south"), false, false, false, false, false, false, south, new HashMap<>(), exposedCards));
        playerList.add(new Player("west", cards.get("west"), false, false, false, false, false, false, west, new HashMap<>(), exposedCards));
        playerList.add(new Player("north", cards.get("north"), false, false, false, false, false, false, north, new HashMap<>(), exposedCards));


        game = new Game(playerList, Boolean.TRUE, null, new LinkedList<>(), null);
    }

    private void setCardFlow(String name, String card) {
        if (ObjectUtil.equal(name, "north")) {
            ImageView imageView = new ImageView();
            imageView.setId(card);
            imageView.setFitWidth(53);
            imageView.setFitHeight(75);
            imageView.setPreserveRatio(true);
            imageView.setPickOnBounds(true);

            imageView.setImage(new Image(CommonService.getPicUrl("/img/vertical.jpg")));
            north.getChildren().add(imageView);
        } else if (ObjectUtil.equal(name, "east")) {
            ImageView imageView = new ImageView();
            imageView.setId(card);
            imageView.setFitWidth(75);
            imageView.setFitHeight(53);
            imageView.setPreserveRatio(true);
            imageView.setPickOnBounds(true);

            imageView.setImage(new Image(CommonService.getPicUrl("/img/horizontal.jpg")));
            east.getChildren().add(imageView);
        } else if (ObjectUtil.equal(name, "south")) {

            ImageView imageView = new ImageView();
            imageView.setId(card);
            imageView.setFitWidth(53);
            imageView.setFitHeight(75);
            imageView.setPreserveRatio(true);
            imageView.setPickOnBounds(true);
            imageView.setImage(new Image(CommonService.getPicUrl("/img/" + card + ".jpg")));
            imageView.setOnMouseClicked(e -> {

                if (imageView.getEffect() == null) {
                    if (south.getChildren().stream().filter(c -> c.getEffect() != null).count() == 4) {
                        CommonService.errorDialog("出牌不能超过4张");
                        return;
                    }
                    imageView.setEffect(new DropShadow(15, Color.LIGHTSKYBLUE));
                } else {
                    imageView.setEffect(null);
                }

            });

            south.getChildren().add(imageView);
        } else {
            ImageView imageView = new ImageView();
            imageView.setId(card);
            imageView.setFitWidth(75);
            imageView.setFitHeight(53);
            imageView.setPreserveRatio(true);
            imageView.setPickOnBounds(true);

            imageView.setImage(new Image(CommonService.getPicUrl("/img/horizontal.jpg")));
            west.getChildren().add(imageView);
        }

    }

    private void print() throws InterruptedException {

        Player eastPlayer = game.getPlayerList().get(0);
        StringBuilder sb = new StringBuilder("[");
        if (!eastPlayer.getFinished()) {
            log.info("east 实际卡牌：{}", eastPlayer.getCards());

            for (Node child : east.getChildren()) {
                sb.append(child.getId()).append(", ");
            }
            if (sb.length() > 2) {
                sb.delete(sb.length() - 2, sb.length());
            }
            log.info("east 拥有卡牌：{}", sb.append("]"));
            int counter = 0;
            while (east.getChildren().size() != eastPlayer.getCards().size()) {
                if (counter < 10) {
                    Thread.sleep(1000);
                    counter++;
                    continue;
                }
                throw new RuntimeException("error east");
            }
        }

        Player southPlayer = game.getPlayerList().get(1);
        sb = new StringBuilder("[");
        if (!southPlayer.getFinished()) {
            log.info("south 实际卡牌：{}", southPlayer.getCards());
            for (Node child : south.getChildren()) {
                sb.append(child.getId()).append(", ");
            }
            if (sb.length() > 2) {
                sb.delete(sb.length() - 2, sb.length());
            }
            log.info("south 拥有卡牌：{}", sb.append("]"));
            int counter = 0;
            while (south.getChildren().size() != southPlayer.getCards().size()) {
                if (counter < 10) {
                    Thread.sleep(1000);
                    counter++;
                    continue;
                }
                throw new RuntimeException("error south");
            }
        }


        Player westPlayer = game.getPlayerList().get(2);
        sb = new StringBuilder("[");
        if (!westPlayer.getFinished()) {
            log.info("west 实际卡牌：{}", westPlayer.getCards());

            for (Node child : west.getChildren()) {
                sb.append(child.getId()).append(", ");
            }
            if (sb.length() > 2) {
                sb.delete(sb.length() - 2, sb.length());
            }
            log.info("west 拥有卡牌：{}", sb.append("]"));
            int counter = 0;
            while (west.getChildren().size() != westPlayer.getCards().size()) {
                if (counter < 10) {
                    Thread.sleep(1000);
                    counter++;
                    continue;
                }
                throw new RuntimeException("error west");
            }
        }


        Player northPlayer = game.getPlayerList().get(3);
        sb = new StringBuilder("[");
        if (!northPlayer.getFinished()) {
            log.info("north 实际卡牌：{}", northPlayer.getCards());

            for (Node child : north.getChildren()) {
                sb.append(child.getId()).append(", ");
            }

            if (sb.length() > 2) {
                sb.delete(sb.length() - 2, sb.length());
            }
            log.info("north 拥有卡牌：{}", sb.append("]"));
            int counter = 0;
            while (north.getChildren().size() != northPlayer.getCards().size()) {
                if (counter < 10) {
                    Thread.sleep(1000);
                    counter++;
                    continue;
                }
                throw new RuntimeException("error north");
            }
        }

    }

    private void showTip(String text) throws InterruptedException {
        log.info(text);
        Label label = new Label();
        label.setPrefWidth(670);
        label.setPrefHeight(36);
        label.setText(text);
        label.setAlignment(Pos.CENTER);

        if (Thread.currentThread().getId() == thread.getId()) {
            CommonService.runLater(() -> {
                stage.getChildren().add(label);
                scrollPane.vvalueProperty().setValue(1.0);
            });
        } else {
            stage.getChildren().add(label);
            scrollPane.vvalueProperty().setValue(1.0);
        }

    }

    private void saveCard() {
        //保存每个玩家各自过掉的牌
        for (Map<String, List<String>> map : game.getFieldList()) {
            for (Map.Entry<String, List<String>> entry : map.entrySet()) {

                Set<String> set = entry.getValue().stream()
                        .map(c -> c.substring(1)).collect(Collectors.toSet());
                Map<String, Boolean> passCards = game.getPlayerList().stream()
                        .filter(p -> ObjectUtil.equal(p.getName(), entry.getKey()))
                        .findFirst().get()
                        .getPassCards();
                for (String s : set) {
                    passCards.putIfAbsent(s, false);
                }
            }

        }
    }

    private boolean end(Player startPlayer) throws InterruptedException {
        boolean hasEnd = game.getPlayerList().stream()
                .filter(p -> ObjectUtil.notEqual(p.getName(), startPlayer.getName()))
                .allMatch(Player::getFinished);
        if (hasEnd) {
            log.info("游戏结束,玩家 {} 败北", startPlayer.getName());
            game.setIsStarted(false);

            if (Thread.currentThread().getId() == thread.getId()) {
                Runnable r = () -> dialog(StrUtil.format("游戏结束,玩家 {} 败北", startPlayer.getName()));
                CommonService.runLater(r);
            } else {
                dialog(StrUtil.format("游戏结束,玩家 {} 败北", startPlayer.getName()));
            }

            return true;
        }
        return false;
    }

    private void dialog(String text) {
        Dialog<Pair<String, String>> dialog = new Dialog<>();
        dialog.initStyle(StageStyle.UTILITY);
        dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);

        DialogPane dialogPane = dialog.getDialogPane();

        Button btnCancel = (Button) dialogPane.lookupButton(ButtonType.CANCEL);
        btnCancel.setPrefWidth(40);
        btnCancel.setPrefHeight(20);
        btnCancel.setText("返回");
        btnCancel.setOnAction(e -> CommonService.jumpButtonEvent(discard, "main"));

        Button applyBtn = (Button) dialogPane.lookupButton(ButtonType.OK);
        applyBtn.setPrefWidth(40);
        applyBtn.setPrefHeight(20);
        applyBtn.setText("重玩");
        applyBtn.setOnAction(e -> {
            stage.getChildren().clear();
            PokerGen.genNewCard();
            showCard(PokerGen.distributeCard());
            new Thread(() -> {
                try {
                    startGame();
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }).start();
        });

        Label label = new Label(text);
        label.setWrapText(true);
        label.setPrefWidth(150);
        label.setPrefHeight(100);

        dialog.getDialogPane().setContent(label);
        dialog.showAndWait();
    }
}
